package com.ht.api.util;

import java.util.HashMap;
import java.util.Map;

import com.ht.api.constant.CacheConstants;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

/**
 * JWT(Json web token)工具类
 * @author asq
 * @createTime 2024年12月21日 11:22:10
 */
@Slf4j
public class JwtUtils {
	/** token名称 */
	public static final String TOKEN_KEY = "token";
	/** 密钥 */
	private static final byte[] KEY = "didkHtow_*&%de(92ke`2".getBytes();

	/**
	 * 生成token
	 */
	public static String createToken(Map<String, Object> payload) {
		DateTime now = DateTime.now();

		// 添加标准声明
		Map<String, Object> claims = new HashMap<>(payload);
		claims.put("iat", now.getTime()); // 签发时间
		claims.put("exp", now.getTime() + CacheConstants.EXPIRE_TOKEN * 1000); // 过期时间

		return JWTUtil.createToken(claims, KEY);
	}

	/**
	 * 验证token
	 */
	public static boolean verify(String token, String uuid) {
		try {
			// 解析token
			JWT jwt = JWTUtil.parseToken(token);
			if (jwt == null) {
				return false;
			}

			// 1. 验证签名
			if (!JWTUtil.verify(token, KEY)) {
				log.warn("token签名验证失败");
				return false;
			}

			// 2. 验证是否过期
			long exp = getPayloadAsLong(jwt, "exp");
			if (System.currentTimeMillis() > exp) {
				log.warn("token已过期");
				return false;
			}

			// 3. 验证uuid 
			String loginUuid = getPayloadAsString(jwt, "uuid");
			if (!loginUuid.equals(uuid)) {
				log.warn("token的uuid无效");
				return false;
			}

			return true;
		} catch (Exception e) {
			log.error("JWT验证失败", e);
			return false;
		}
	}

	/**
	 * 解析token
	 */
	public static JWT parseToken(String token) {
		try {
			return JWTUtil.parseToken(token);
		} catch (Exception e) {
			log.error("JWT解析失败", e);
			return null;
		}
	}

	/**
	 * 获取载荷信息
	 */
	public static String getPayloadAsString(JWT jwt, String key) {
		return Convert.toStr(jwt.getPayload(key));
	}

	/**
	 * 获取载荷信息
	 */
	public static int getPayloadAsInteger(JWT jwt, String key) {
		return Convert.toInt(jwt.getPayload(key));
	}
	
	/**
	 * 获取载荷信息
	 */
	public static long getPayloadAsLong(JWT jwt, String key) {
		return Convert.toLong(jwt.getPayload(key));
	}

	/**
	 * 获取载荷信息
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getPayload(String token, String key) {
		try {
			JWT jwt = parseToken(token);
			return jwt != null ? (T) jwt.getPayload(key) : null;
		} catch (Exception e) {
			log.error("获取JWT载荷失败", e);
			return null;
		}
	}

	/**
	 * 获取登陆用户名
	 * @param req
	 * @return
	 */
	public static String getUsername(HttpServletRequest req) {
		String header = req.getHeader(TOKEN_KEY);
		if (header == null || header.isEmpty())
			header = req.getParameter(TOKEN_KEY);
		if (header == null || header.isEmpty())
			return null;
		return getUsername(header);
	}

	/**
	 * 获得token中的信息无需secret解密也能获得
	 * @return token中包含的用户名
	 */
	public static String getUsername(String token) {
		return getPayload(token, "username");
	}
}
